from sqlalchemy.ext.asyncio import AsyncSession as Session
from app.models.xm.monitor_buy import MonitorBuy
from app.schemas.xm.monitor_buy import MonitorBuyCreate, MonitorBuyOut
from sqlalchemy import select
from datetime import datetime
from fastapi.exceptions import HTTPException
from app.core.constants import MonitorBuyStatus

async def create_monitor_buy(session: Session, monitor_buy: MonitorBuyCreate) -> MonitorBuy:
    db_monitor_buy = MonitorBuy(**monitor_buy.model_dump())
    session.add(db_monitor_buy)
    await session.commit()
    await session.refresh(db_monitor_buy)
    return db_monitor_buy

async def get_monitor_buy(session: Session, monitor_buy_id: int) -> MonitorBuy:
    result = await session.execute(select(MonitorBuy).filter(MonitorBuy.id == monitor_buy_id))
    return result.scalar_one_or_none()

async def get_by_user_archive_price(
    session: Session,
    uid: int,
    archiveId: int,
    buyPrice: int,
) -> MonitorBuyOut:
    """根据用户ID和藏品ID获取监控购买记录"""
    statement = select(MonitorBuy)
    statement = statement.filter(
        MonitorBuy.uid == uid, 
        MonitorBuy.archiveId == archiveId, 
        MonitorBuy.buyPrice == buyPrice, 
        MonitorBuy.status == MonitorBuyStatus.MONITORING,
        MonitorBuy.expireAt > datetime.now()
    )
    result = await session.execute(statement)
    return result.scalars().first()

async def get_monitor_buy_page(
    session: Session, 
    archiveId: int,
    pageNo: int = 1,
    pageSize: int = 100,
) -> list[MonitorBuyOut]:
    """获取监控购买列表"""
    statement = select(MonitorBuy)
    # 查询过滤
    statement = statement.filter(MonitorBuy.archiveId == archiveId, MonitorBuy.status == MonitorBuyStatus.MONITORING)
    # 过滤已过期的监控
    statement = statement.filter(MonitorBuy.expireAt > datetime.now())

    # 计算总数
    total = await session.execute(statement)
    total = len(total.scalars().all())

    # 排序，按购买价格降序，监控开始时间升序
    statement = statement.order_by(MonitorBuy.buyPrice.desc(), MonitorBuy.createdAt.asc())
    # 分页查询
    statement = statement.offset((pageNo - 1) * pageSize).limit(pageSize)
    result = await session.execute(statement)
    return {
        "records": [MonitorBuyOut.model_validate(monitor_buy) for monitor_buy in result.scalars().all()],
        "total": total,
        "pageNo": pageNo,
        "pageSize": pageSize
    }

async def get_monitor_buy_by_uid(
    session: Session,
    uid: int
) -> list[MonitorBuyOut]:
    """根据用户ID和监控购买ID获取监控购买记录"""
    # 查询过滤
    statement = select(MonitorBuy)
    statement = statement.filter(MonitorBuy.uid == uid, MonitorBuy.status == MonitorBuyStatus.MONITORING)
    # 过滤已过期的监控
    statement = statement.filter(MonitorBuy.expireAt > datetime.now())
    # 排序，按购买价格降序，监控开始时间升序
    statement = statement.order_by(MonitorBuy.buyPrice.desc(), MonitorBuy.createdAt.asc())
    result = await session.execute(statement)
    return [MonitorBuyOut.model_validate(monitor_buy) for monitor_buy in result.scalars().all()]

async def expire_monitor_buy(
    session: Session,
    uid: int,
    monitor_buy_id: int,
) -> MonitorBuyOut:
    """取消用户购买的监控"""
    monitor_buy = await get_monitor_buy(session, monitor_buy_id)
    if not monitor_buy:
        raise HTTPException(status_code=404, detail="Monitor buy not found")
    if monitor_buy.uid != uid:
        raise HTTPException(status_code=403, detail="Not authorized to cancel this monitor buy")
    if monitor_buy.status != 0:
        raise HTTPException(status_code=400, detail="Monitor buy is not active")
    monitor_buy.status = MonitorBuyStatus.CANCELLED
    monitor_buy.expireAt = datetime.now()
    await session.commit()
    await session.refresh(monitor_buy)
    return MonitorBuyOut.model_validate(monitor_buy)

# 查询用户监控XM挂单藏品ID列表，Group By archiveId
async def get_monitor_buy_archive_ids(
    session: Session,
) -> list[int]:
    """根据用户ID获取监控购买的藏品ID列表"""
    statement = select(MonitorBuy.archiveId)
    statement = statement.filter(MonitorBuy.status == MonitorBuyStatus.MONITORING)
    # 过滤已过期的监控
    statement = statement.filter(MonitorBuy.expireAt > datetime.now())
    # 分组查询
    statement = statement.group_by(MonitorBuy.archiveId)
    result = await session.execute(statement)
    return [archiveId for archiveId in result.scalars().all()]

# 查询藏品最高价格监控挂单
async def get_monitor_buy_max_price(
    session: Session,
    archiveId: int,
) -> MonitorBuy:
    """根据藏品ID获取监控购买的最高价格"""
    statement = select(MonitorBuy)
    statement = statement.filter(MonitorBuy.archiveId == archiveId, MonitorBuy.status == MonitorBuyStatus.MONITORING)
    # 过滤已过期的监控
    statement = statement.filter(MonitorBuy.expireAt > datetime.now())
    # 排序，按购买价格降序
    statement = statement.order_by(MonitorBuy.buyPrice.desc())
    result = await session.execute(statement)
    return result.scalars().first()

# 更新已购买数量
async def update_buy_count(
    session: Session,
    monitor_buy: MonitorBuy,
    buy_count: int,
) -> MonitorBuy:
    """更新监控购买的已购买数量"""
    monitor_buy.boughtNum += buy_count
    # 检查是否已购买完成
    if monitor_buy.boughtNum >= monitor_buy.maxBuyNum:
        monitor_buy.status = MonitorBuyStatus.COMPLETED
    await session.commit()
    await session.refresh(monitor_buy)
    return monitor_buy

async def update_monitor_buy_pause(
    session: Session,
    monitor_buy: MonitorBuy,
    status: MonitorBuyStatus,
    pauseRemark: str,
) -> MonitorBuy:
    """更新监控购买的状态"""
    monitor_buy.status = status
    monitor_buy.pauseRemark = pauseRemark
    await session.commit()
    await session.refresh(monitor_buy)
    return monitor_buy
